package com.dtflys.easyel.transform;

import com.dtflys.easyel.antlr.EasyElParser;
import com.dtflys.easyel.ast.ASTBinaryExpression;
import com.dtflys.easyel.ast.ASTExpression;
import com.dtflys.easyel.ast.ASTType;
import org.antlr.v4.runtime.CommonToken;
import org.antlr.v4.runtime.Token;
import org.antlr.v4.runtime.misc.Pair;

/**
 * @author gongjun[jun.gong@thebeastshop.com]
 * @since v1.0.0
 */
public class BinaryExpressionTransformer extends ExpressionTransformer {

    public ASTBinaryExpression transform(
            ASTExpression leftExpr,
            Token opToken,
            Token notToken,
            ASTExpression rightExpr) {

        ASTType type = null;
        switch (opToken.getType()) {
            case EasyElParser.IN:
                if (notToken != null) {
                    Pair source = new Pair(opToken.getTokenSource(), opToken.getInputStream());
                    opToken = new CommonToken(
                            source,
                            EasyElParser.NOT_IN,
                            opToken.getChannel(),
                            notToken.getStartIndex(), opToken.getStopIndex());
                }
            case EasyElParser.AND:
            case EasyElParser.OR:
            case EasyElParser.J_AND:
            case EasyElParser.J_OR:
            case EasyElParser.GT:
            case EasyElParser.GE:
            case EasyElParser.LT:
            case EasyElParser.LE:
            case EasyElParser.EQ:
            case EasyElParser.NOT_IN:
            case EasyElParser.NOT_EQ:
            case EasyElParser.REGEX_MATCH:
            case EasyElParser.NOT_REGEX_MATCH:
                type = ASTType.BOOLEAN;
                break;
            case EasyElParser.ADD:
            case EasyElParser.SUB:
            case EasyElParser.MUL:
            case EasyElParser.DIV:
            case EasyElParser.MOD:
                if (leftExpr.getType() == ASTType.INTEGER) {
                    if (rightExpr.getType() == ASTType.INTEGER) {
                        type = ASTType.INTEGER;
                    } else if (rightExpr.getType() == ASTType.NUMERIC) {
                        type = ASTType.NUMERIC;
                    } else {
                        type = ASTType.STRING;
                    }
                } else if (leftExpr.getType() == ASTType.NUMERIC) {
                    type = ASTType.NUMERIC;
                } else {
                    type = leftExpr.getType();
                }
                break;
        }
        ASTBinaryExpression binaryExpression = new ASTBinaryExpression(type, leftExpr, opToken, rightExpr);
        setPosition(binaryExpression, leftExpr, rightExpr);
        printNode(binaryExpression);
        return binaryExpression;
    }

}
